/**
 * @Copyright 2012, Founder Mobile Media Technology（Chongqing） Co., Ltd L.P. All
 *            rights reserved. The information contained herein is confidential
 *            and proprietary to Founder Mobile Media Technology（Chongqing） Co.,
 *            Ltd, and considered a trade secret as defined under civil and
 *            criminal statutes. Founder Mobile Media Technology（Chongqing） Co.,
 *            Ltd shall pursue its civil and criminal remedies in the event of
 *            unauthorized use or misappropriation of its trade secrets. Use of
 *            this information by anyone other than authorized employees of
 *            Founder Mobile Media Technology（Chongqing） Co., Ltd is granted
 *            only under a written non-disclosure agreement, expressly
 *            prescribing the scope and manner of such use.
 */
package com.g2room.quartz.engine;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.DateBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;

import com.g2room.quartz.Jobs;

/**
 * Quartz核心引擎类，创建新的Schedule。并调度定时任务
 *
 * @createTime: Apr 18, 2013 9:09:32 PM
 * @author: <a href="mailto:gaoxg@FOUNDER.COM.CN">Xuguo Gao</a>
 * @version: 0.1
 * @lastVersion: 0.1
 * @updateTime: 
 * @updateAuthor: <a href="mailto:gaoxg@FOUNDER.COM.CN">Xuguo Gao</a>
 * @changesSum: 
 * 
 */
public class QuartzEngine1 {
	/** Quartz任务调度工厂 */
	private static SchedulerFactory schedulerFactory = new StdSchedulerFactory();
	/**
	 * 获取Quartz任务调度工厂实例类
	 *
	 * @return {SchedulerFactory}
	 * @auther <a href="mailto:gaoxg@FOUNDER.COM.CN">Gao Xuguo</a>
	 * May 30, 2013 11:13:49 PM
	 */
	public static SchedulerFactory getSchedulerFactory(){
		return schedulerFactory;
	}
	
	/**
	 * 使用quartz实现的调度任务
	 *
	 * @throws SchedulerException
	 * @throws InterruptedException
	 * @auther <a href="mailto:gaoxg@FOUNDER.COM.CN">Gao Xuguo</a>
	 * May 9, 2013 4:43:01 PM
	 */
	public static void jobSchedule() throws SchedulerException,InterruptedException {
		// 获取Quartz任务调度工厂
		SchedulerFactory factory = new StdSchedulerFactory();
		// 从工厂里面拿到一个scheduler实例
		Scheduler scheduler = factory.getScheduler();
	// 计算任务的开始时间，DateBuilder.evenMinuteDate方法是取下一个整数分钟
//	Date runTime = DateBuilder.evenMinuteDate(new Date());
	// 任务的开始时间，nextGivenSecondDate方法表示：
	// 启动后16秒运行
	Date runTime = DateBuilder.nextGivenSecondDate(null, 16);
	
	// 简单例子
	// 真正执行的任务并不是Job接口的实例，而是用反射的方式实例化的一个Jobs实例
//	JobDetail job = JobBuilder.newJob(Jobs.class).withIdentity("job1", "testGroup").build();
//	// 定义一个触发器，startAt方法定义了任务应当开始的时间
//	Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1",
//			"testGroup").startAt(runTime).build();
//	// 将任务和Trigger放入scheduler
//	scheduler.scheduleJob(job, trigger);

	// 将同一个Job实现作为另外一个任务注册到scheduler，注意名字要区分
//	job = JobBuilder.newJob(Jobs.class).withIdentity("job2", "testGroup").build();
//	trigger = TriggerBuilder.newTrigger().withIdentity("trigger2", 
//			"testGroup").startAt(runTime).build();
//	scheduler.scheduleJob(job, trigger);

//	// @NOTICE
//	// 重复执行,job3表示第一次执行完之后，每隔3秒钟执行一次，重复5次，
	// withRepeatCount参数不包括第一次执行那次，即job3总共执行6次
	// SimpleScheduleBuilder：	重复执行，需要在Trigger的设置里面加入，
	// 							设置重复次数和重复时间即可。
	// repeatForever()方法永远表示一直重复执行，相应的可以设置按小时、分钟、秒一直执行。
	JobDetail job = JobBuilder.newJob(Jobs.class).withIdentity("job3", "testGroup").build();
	job.getJobDataMap().put(Jobs.JOB_DATA_MAP_KEY, 10); 
//	Trigger trigger = TriggerBuilder.newTrigger()
//			.withIdentity("trigger3", "testGroup").withSchedule(
//					SimpleScheduleBuilder.simpleSchedule().withRepeatCount(4)
//					.withIntervalInSeconds(2))
//			.startAt(runTime).build();
//	/**
//	 	// 无trigger注册，表示任务立即执行。
//		scheduler.addJob(job, true);
//		// 在scheduler.start之后调用，可以在job开始后重新定义trigger，然后重新注册。
//			scheduler.rescheduleJob(trigger.getKey(), trigger);
//			// 可以在shutdown后取出执行的任务数量，一些基本信息封装在SchedulerMetaData对象中。 
//		scheduler.getMetaData().getNumberOfJobsExecuted(); 
//	 */
//	scheduler.scheduleJob(job, trigger);
	/**
		与SimpleTrigger对比：类不同了，现在的是Trigger的子类CronTrigger；
		withSchedule中的参数变为CronScheduleBuilder了  
	    CronScheduleBuilder可以通过类似"0/13 * * * * ?"这种表达式来创建定时任务  
	    当前这个表达式的定义是每个秒是13的倍数，或者是0的时候，都触发任务
		*/
  	CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(
			"trigger3", "testGroup").withSchedule(
			CronScheduleBuilder.cronSchedule("0 0 03 * * ?")).build();
  	/**
  	--------------------------------------
  	   秒 分 时  日 月 周 年
  	   0 0  12  *  * ?         每天12点触发
  	   0 15 10  ?  * *         每天10点15分触发
  	   0 15 10  *  * ?         每天10点15分触发
  	   0 15 10  *  * ? *       每天10点15分触发
  	   0 15 10 * * ? 2005      2005年每天10点15分触发
  	   0 * 14 * * ?            每天下午的 2点到2点59分每分触发
  	   0 0/5 14 * * ?          每天下午的 2点到2点59分(整点开始，每隔5分触发)
  	   0 0/5 14,18 * * ?       每天下午的 2点到2点59分(整点开始，每隔5分触发) 每天下午的 18点到18点59分(整点开始，每隔5分触发)
  	   0 0-5 14 * * ?          每天下午的 2点到2点05分每分触发
  	   0 10,44 14 ? 3 WED      3月分每周三下午的 2点10分和2点44分触发
  	   0 15 10 ? * MON-FRI     从周一到周五每天上午的10点15分触发
  	   0 15 10 15 * ?          每月15号上午10点15分触发
  	   0 15 10 L * ?           每月最后一天的10点15分触发
  	   0 15 10 ? * 6L          每月最后一周的星期五的10点15分触发
  	   0 15 10 ? * 6L 2002-2005    从2002年到2005年每月最后一周的星期五的10点15分触发
  	   0 15 10 ? * 6#3         每月的第三周的星期五开始触发
  	   0 0 12 1/5 * ?          每月的第一个中午开始每隔5天触发一次
  	   0 11 11 11 11 ?         每年的11月11号 11点11分触发(光棍节)
  	--------------------------------------
  	其次，通配符，主要的有星号(*)；问号(?)；减号(-)；逗号(,)；斜杠(/)；L字母；W字母；井号(#). 
	星号：表示任意时刻
	问号：只能在日或周字段上使用，http://blog.csdn.net/chh_jiang/article/details/4603529 这里有比较清晰的解释，简单的理解就是日期和星期是有冲突的，指定其中一个的话，另外一个是没办法指定的，比如每个月12号和每个星期二，这两个是"互斥"的，不能用日期和周来指定所有“每个是星期二的12号”这个时间。
	减号：范围，如 1-5秒
	逗号：列表，如 1,5,10 秒
	斜杠：等步长序列，如3/13秒 表示 3,16,29,42,55,3,16...
	L：仅在日和周上支持，表示允许的最后一个值，注意不要让范围和列表与L连用
	W：工作日
	井号：为给定月份指定具体的工作日实例。把“MON#2”放在周内日期字段中，表示把任务安排在当月的第二个星期一。
	井号和L W用的比较少，其实简单实用的话，根据那些注释中的去改就够了~~
  	*/
  	scheduler.scheduleJob(job, cronTrigger);
	// 开始调度
	scheduler.start();
	try {
//		// 等待65秒，保证下一个整数分钟出现，这里注意，如果主线程停止，任务是不会执行的
//		Thread.sleep(5L * 1000L);
		Thread.sleep(2000L * 1000L);
	} catch (Exception e) {
	}
	// scheduler结束
	scheduler.shutdown(true);
	System.out.println("==============" + scheduler.getMetaData().getNumberOfJobsExecuted());
}
}
